package com.linq.cool.beauty.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.linq.cool.api.domain.BeautyMember;
import com.linq.cool.api.dto.BeautyMemberBindDTO;
import com.linq.cool.api.dto.BeautyMemeberRegisterDTO;
import com.linq.cool.api.vo.WebLoginUser;
import com.linq.cool.beauty.config.AlipayConfig;
import com.linq.cool.beauty.domain.BeautyRefund;
import com.linq.cool.beauty.domain.BeautyTopUp;
import com.linq.cool.beauty.dto.*;
import com.linq.cool.beauty.service.AlipayService;
import com.linq.cool.beauty.service.BeautyMemberService;
import com.linq.cool.beauty.service.BeautyRefundService;
import com.linq.cool.beauty.service.BeautyTopUpService;
import com.linq.cool.beauty.vo.AlipayRefundVO;
import com.linq.cool.beauty.vo.AlipayVO;
import com.linq.cool.beauty.vo.BeautyMemberTopUpVO;
import com.linq.cool.common.constants.UserConstants;
import com.linq.cool.common.core.domain.BaseController;
import com.linq.cool.common.core.domain.PageVO;
import com.linq.cool.common.core.domain.Result;
import com.linq.cool.common.core.utils.IdWorker;
import com.linq.cool.common.core.utils.JwtUtils;
import com.linq.cool.common.core.utils.RegexUtils;
import com.linq.cool.common.core.utils.SecurityUtils;
import com.linq.cool.common.log.annotation.Log;
import com.linq.cool.common.log.enums.BusinessType;
import com.linq.cool.common.security.annotation.PreAuthorize;
import com.linq.cool.common.security.service.WebTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;

/**
 * @Author: yqlin
 * @Date: 2021/1/30 21:18
 * @Description:
 * @Version: 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("member")
public class BeautyMemberController extends BaseController {
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private BeautyMemberService beautyMemberService;
    @Autowired
    private BeautyTopUpService beautyTopUpService;
    @Autowired
    private BeautyRefundService beautyRefundService;
    @Autowired
    private WebTokenService webTokenService;

    @PreAuthorize(hasPerm = "beauty:member:list")
    @GetMapping("list")
    public Result<?> list(BeautyMemberQueryDTO dto) {
        IPage<BeautyMember> page = beautyMemberService.listByPage(dto.getPage(), dto);
        return Result.ok(new PageVO().setTotal(page.getTotal()).setRecords(page.getRecords()));
    }

    @GetMapping(value = "{memberId}")
    public Result<?> getInfo(@PathVariable("memberId") Long memberId) {
        return Result.ok(beautyMemberService.getById(memberId));
    }

    @Log(moduleTitle = "客户管理", businessType = BusinessType.INSERT)
    @PreAuthorize(hasPerm = "beauty:member:add")
    @PostMapping
    public Result<?> add(@Validated @RequestBody BeautyMemberDTO dto) {
        if (!RegexUtils.checkMobile(dto.getPhone())) {
            return Result.fail("手机号不合法");
        }
        if (!RegexUtils.checkIdCard(dto.getIdNumber())) {
            return Result.fail("身份证号码不合法");
        }
        return this.toResult(beautyMemberService.saveMember(dto));
    }

    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:edit")
    @PutMapping
    public Result<?> edit(@Validated @RequestBody BeautyMemberDTO dto) {
        if (!RegexUtils.checkMobile(dto.getPhone())) {
            return Result.fail("手机号不合法");
        }
        if (!RegexUtils.checkIdCard(dto.getIdNumber())) {
            return Result.fail("身份证号码不合法");
        }
        return this.toResult(beautyMemberService.updateMember(dto));
    }

    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:remove")
    @DeleteMapping("{memberId}")
    public Result<?> remove(@PathVariable("memberId") Long memberId) {
        // 根据客户id查询当前客户信息
        BeautyMember member = beautyMemberService.getById(memberId);
        member.setIsDeleted(UserConstants.StateEnum.DELETE_FLAG_DELETED.getCode());
        return this.toResult(beautyMemberService.updateById(member));
    }

    /**
     * 状态修改
     */
    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:edit")
    @PutMapping("changeStatus/{memberId}/{status}")
    public Result<?> changeStatus(@PathVariable("memberId") Long memberId, @PathVariable("status") Integer status) {
        BeautyMember member = new BeautyMember();
        member.setId(memberId).setStatus(status);
        member.setModifier(SecurityUtils.getUserId()).setGmtModified(new Date());
        return this.toResult(beautyMemberService.updateById(member));
    }

    /**
     * 支付宝充值金额
     *
     * @return
     */
    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PutMapping("alipay/topUp")
    public Result<?> topUpWithAlipay(@Validated @RequestBody BeautyMemberTopUpDTO dto) {
        Integer loginType = JwtUtils.getLoginType(SecurityUtils.getToken());
        final String orderId = idWorker.nextId() + "";
        BeautyTopUp topUpLog = new BeautyTopUp();
        topUpLog.setId(orderId)
                .setMemberId(dto.getMemberId())
                .setRestAmount(dto.getAmount())
                .setAmount(dto.getAmount());
        if (UserConstants.StateEnum.LOGIN_TYPE_SYSTEM.getCode().equals(loginType)) {
            topUpLog.setCreator(SecurityUtils.getUserId());
        }
        // 保存日志
        beautyTopUpService.save(topUpLog);
        //因为是支付宝支付，所以我们要返回给页面一个二维码
        AlipayPayDTO payDTO = new AlipayPayDTO();
        payDTO.setOutTradeNo(orderId)
                .setSubject("LINQ-CAR支付平台")
                .setTotalAmount(dto.getAmount().toString())
                .setBody("LINQ-CAR平台充值积分:" + dto.getAmount().toString())
                .setUndiscountableAmount(null)
                .setNotifyUrl(AlipayConfig.notifyUrl + orderId);
        Result<?> alipayResult = AlipayService.pay(payDTO);
        if (alipayResult.getData() != null) {
            AlipayVO alipayVO = (AlipayVO) alipayResult.getData();
            return Result.ok(new BeautyMemberTopUpVO().setAmount(dto.getAmount())
                                     .setOrderId(orderId).setPayUrl(alipayVO.getQrCode())
            );
        }
        return alipayResult;
    }

    /**
     * 现金充值
     *
     * @param dto
     *
     * @return
     */
    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:topUp")
    @PutMapping("cash/topUp")
    public Result<?> topUpWithCash(@Validated @RequestBody BeautyMemberTopUpDTO dto) {
        return this.toResult(beautyMemberService.topUpWithCash(dto));
    }


    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:refund")
    @PutMapping("alipay/refund")
    public Result<?> refundWithAlipay(@Validated @RequestBody BeautyRefundDTO dto) {
        // 先判断充值订单是否已经变成已退费状态 如果已经变成了 就不执行下面的操作了
        BeautyTopUp preTopUp = beautyTopUpService.getById(dto.getTopUpId());
        if (null == preTopUp) {
            return Result.fail(String.format("充值订单号[%s]的之前没有收费记录，不能使用支付宝退费，请核对后再查询", dto.getTopUpId()));
        }
        if (UserConstants.StateEnum.ORDER_STATUS_4.getCode().equals(preTopUp.getStatus())) {
            return Result.fail("该订单已退费");
        }
        // 判断之前是否使用支付宝支付
        if (!UserConstants.StateEnum.PAY_TYPE_ALIPAY.getCode().equals(preTopUp.getPayType())) {
            return Result.fail(String.format("订单号[%s]的之前的支付方式为现金或微信，不能使用支付宝退费，请核对后再查询", dto.getTopUpId()));
        }
        // a<b, 返回-1
        // a=b，返回0
        // a>b, 返回1
        if (dto.getAmount().compareTo(preTopUp.getAmount()) > 0) {
            return Result.fail("退费金额超过充值金额");
        }
        // 保存退费订单
        BeautyRefund refund = new BeautyRefund();
        final String refundId = idWorker.nextId() + "";
        refund.setId(refundId)
                .setAmount(dto.getAmount())
                .setTopUpId(preTopUp.getId())
                .setMemberId(preTopUp.getMemberId())
                .setMemberPhone(preTopUp.getMemberPhone())
                .setMemberRealName(preTopUp.getMemberRealName())
                .setCreator(SecurityUtils.getUserId());
        // 判断退费订单是全额退款还是部分退款
        if (dto.getAmount().compareTo(preTopUp.getAmount()) == 0 && dto.getAmount().compareTo(preTopUp.getRestAmount()) == 0) {
            // 全额
            refund.setType(UserConstants.StateEnum.ORDER_REFUND_TYPE_0.getCode());
        } else {
            // 部分退款
            refund.setType(UserConstants.StateEnum.ORDER_REFUND_TYPE_1.getCode());
        }
        beautyRefundService.save(refund);
        // 因为是支付宝退费，所以调用支付宝的接口
        AlipayRefundDTO refundDTO = new AlipayRefundDTO();
        refundDTO.setOutTradeNo(dto.getTopUpId())
                .setTradeNo(preTopUp.getPayPlatformId())
                .setRefundAmount(dto.getAmount().toString())
                .setRefundReason("LINQ-CAR内部退费")
                .setOutRequestNo(refundId);
        Result<?> payBackResult = AlipayService.payBack(refundDTO);
        if (Result.SUCCESS.equals(payBackResult.getCode())) {
            AlipayRefundVO refundVO = (AlipayRefundVO) payBackResult.getData();
            beautyRefundService.refundSuccess(refundId, refundVO.getTradeNo(), UserConstants.StateEnum.PAY_TYPE_ALIPAY.getCode());
            return Result.ok("退费成功");
        } else {
            return Result.fail(payBackResult.getMessage());
        }
    }


    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:refund")
    @PutMapping("cash/refund")
    public Result<?> refundWithCash(@Validated @RequestBody BeautyRefundDTO dto) {
        return this.toResult(beautyMemberService.refundWithCash(dto));
    }


    /**
     * 根据openid获取客户信息
     *
     * @param openId Openid
     *
     * @return
     */
    @GetMapping("info/{openId}")
    public Result<?> getMemberInfo(@PathVariable("openId") String openId) {
        BeautyMember one = beautyMemberService.getByOpenId(openId);
        if (null == one) {
            return Result.fail("用户不存在");
        }
        return Result.ok(one.toWeChatLoginUser());
    }

    /**
     * 注册客户
     *
     * @param member 客户信息
     *
     * @return
     */
    @PostMapping("wxRegister")
    public Result<?> wxRegister(@RequestBody BeautyMember member) {
        member.setId(idWorker.nextId());
        return this.toResult(beautyMemberService.save(member));
    }

    /**
     * 绑定客户
     *
     * @param dto
     *
     * @return
     */
    @PostMapping("bindMember")
    public Result<?> bindMember(@RequestBody BeautyMemberBindDTO dto) {
        log.info("openId:{}", SecurityUtils.getOpenId());
        return Result.ok(beautyMemberService.bineMember(dto));
    }


    /**
     * 获取客户下拉列表
     *
     * @return
     */
    @PreAuthorize(hasPerm = "beauty:member:query")
    @GetMapping("getOptionSelect")
    public Result<?> getOptionSelect() {
        return Result.ok(beautyMemberService.list(new LambdaQueryWrapper<BeautyMember>()
                                                          .select(BeautyMember::getId, BeautyMember::getPhone, BeautyMember::getRealName)
                                                          .eq(BeautyMember::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
        ));
    }

    /**
     * 根据手机号获取前台登录用户
     *
     * @param phone
     *
     * @return
     */
    @GetMapping("frontInfo/{phone}")
    Result<WebLoginUser> getFrontMemberInfo(@PathVariable("phone") String phone) {
        BeautyMember one = beautyMemberService.getOne(new LambdaQueryWrapper<BeautyMember>()
                                                              .eq(BeautyMember::getPhone, phone)
                                                              .eq(BeautyMember::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
        );
        if (null == one) {
            return Result.fail("用户不存在");
        }
        return Result.ok(one.toWebLoginUser());
    }

    /**
     * 获取当前客户登录信息
     * getInfo
     *
     * @return
     */
    @GetMapping("getInfo")
    Result<?> getInfo() {
        BeautyMember memberInfo = beautyMemberService.getById(SecurityUtils.getUserId());
        memberInfo.setPassword(null);
        return Result.ok(memberInfo);
    }

    /**
     * 重置密码
     */
    @Log(moduleTitle = "客户管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "beauty:member:edit")
    @PutMapping("resetPwd")
    public Result<?> resetPwd(@Validated @RequestBody BeautyMemberResetPasswordDTO dto) {
        BeautyMember member = new BeautyMember().setId(dto.getId()).setPassword(dto.getPassword());
        member.setPassword(SecurityUtils.encryptPassword(member.getPassword()));
        member.setModifier(SecurityUtils.getUserId()).setGmtModified(new Date());
        return this.toResult(beautyMemberService.updateById(member));
    }

    /**
     * 前台注册
     *
     * @param dto
     *
     * @return
     */
    @PostMapping("frontRegister")
    public Result<?> frontRegister(@Validated @RequestBody BeautyMemeberRegisterDTO dto) {
        if (!RegexUtils.checkMobile(dto.getPhone())) {
            return Result.fail("手机号不合法");
        }
        return this.toResult(beautyMemberService.frontRegister(dto));
    }

    /**
     * 更新客户头像
     *
     * @return
     */
    @PutMapping("updateMemberAvatar")
    public Result<?> updateMemberAvatar(@RequestBody BeautyMemberModifyDTO dto) {
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        member.setAvatar(dto.getAvatar())
                .setGmtModified(new Date());
        // 更新缓存中的头像
        WebLoginUser loginUser = webTokenService.getLoginUser();
        loginUser.setAvatar(dto.getAvatar());
        webTokenService.setLoginUser(loginUser);
        return this.toResult(beautyMemberService.updateById(member));
    }

    /**
     * 修改基本资料
     *
     * @param dto
     *
     * @return
     */
    @PutMapping("updateMemberBasicInfo")
    public Result<?> updateMemberBasicInfo(@RequestBody BeautyMemberModifyDTO dto) {
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        member.setNote(dto.getNote())
                .setNickname(dto.getNickname())
                .setGender(dto.getGender())
                .setGmtModified(new Date());
        // 更新缓存中的信息
        WebLoginUser loginUser = webTokenService.getLoginUser();
        loginUser.setNickname(dto.getNickname())
                .setGender(dto.getGender())
        ;
        webTokenService.setLoginUser(loginUser);
        return Result.ok(beautyMemberService.updateById(member));
    }

    /**
     * 修改密码
     *
     * @param dto
     *
     * @return
     */
    @PutMapping("updateMemberPassword")
    public Result<?> updateMemberPassword(@RequestBody BeautyMemberModifyDTO dto) {
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        if (!SecurityUtils.matchesPassword(dto.getOldPassword(), member.getPassword())) {
            return Result.fail("修改密码失败 ，旧密码错误");
        }
        if (SecurityUtils.matchesPassword(dto.getNewPassword(), member.getPassword())) {
            return Result.fail("新密码不能与旧密码相同");
        }
        member.setPassword(SecurityUtils.encryptPassword(dto.getNewPassword()))
                .setGmtModified(new Date());
        return Result.ok(beautyMemberService.updateById(member));
    }

    /**
     * 完善客户信息
     *
     * @param dto
     *
     * @return
     */
    @PutMapping("perfectMemberInfo")
    public Result<?> perfectMemberInfo(@RequestBody BeautyMemberModifyDTO dto) {
        if (!RegexUtils.checkIdCard(dto.getIdNumber())) {
            return Result.fail("身份证号码不合法");
        }
        return this.toResult(beautyMemberService.perfectMemberInfo(dto));
    }

}
